#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
#include "uart.h"

Uart::Uart(const char *name, int baudRate, int timeOut)
	: baudRate_(baudRate)
	, timeOut_(timeOut)
	, port_(-1)
{
	memset(name_, 0, sizeof(name_));
	strncpy(name_, name, sizeof(name_) - 1);
}

Uart::~Uart() {
	deinit();
}

bool Uart::lock() {
	return true;
}

void Uart::unlock() {}

int Uart::read(void *buf, int size) {
	init();

	pollfd fd;
	fd.fd = port_;
	fd.events = POLLIN;

	int n = 0;

	while (n < size && poll(&fd, 1, timeOut_) > 0 && (fd.revents & POLLIN)) {
		ssize_t nread = ::read(port_, (uint8_t *)buf + n, size - n);
		if (nread <= 0)
			break;
		n += nread;
	}

	return n;
}

void Uart::write(const void *buf, int size) {
	init();
	::write(port_, buf, size);
}

void Uart::clean() {
	init();
	//fflush(port_);
}

void Uart::init() {
	if (port_ >= 0)
		return;

	if ((port_ = open(name_, O_RDWR | O_NOCTTY)) < 0)
		return;

	termios config;
	tcgetattr(port_, &config);

	config.c_oflag &= ~ONLCR;			// Clear ONLCR flag (which appends a CR for every LF)
	cfsetispeed(&config, baudRate_);	// Set baud rate
	cfsetospeed(&config, baudRate_);

	tcsetattr(port_, TCSANOW, &config);
}

void Uart::deinit() {
	if (port_ < 0)
		return;

	close(port_);
	port_ = -1;
}
